<?php
/**
 * Created by PhpStorm.
 * User: 共赢岛
 * Date: 2023/12/15
 * Time: 8:58
 */

namespace App\Services\LifeCycle;


use App\Models\CarPackage;
use App\Models\CarPackageOrder;
use App\Models\CarPackageOrderAttr;
use App\Models\CarPackageType;
use App\Models\Store;
use App\Models\User;
use EasyWeChat\Factory;
use Illuminate\Support\Facades\Auth;

class OrderService
{
    public static function create($param = [])
    {
        $user = Auth::user();
        $package = CarPackage::find($param['package_id']);
        $store = Store::find($param['store_id']);

        if (!$package || !$store) {
            return failureMessage('请确认购买套餐！');
        }

        if ($param['payment_type'] == ORDER_PAYMENT_TYPE_OFFLINE && !$param['remarks_pics']) {
            return failureMessage('请上传身份信息！');
        }

        $order_sn = self::sn();

        if ($param['payment_type'] == ORDER_PAYMENT_TYPE_WECHAT) {
            $app = Factory::payment(config('wechat.payment.default'));

            $result = $app->order->unify([
                'body' => '购买'.$package->title.'套餐',
                'out_trade_no' => $order_sn,
                'total_fee' => app()->environment(['local','staging']) ? 1 : $package['price'] * 100,
                'trade_type' => "JSAPI",
                'spbill_create_ip' => request()->ip(),
                'openid' => $user->app_open_id
            ]);

            $status = ORDER_STATUS_UNPAID;
        } else {
            $status = ORDER_STATUS_EXAMINE;
            $order = CarPackageOrder::where('user_id', $user->id)->where('payment_type', ORDER_PAYMENT_TYPE_OFFLINE)->first();

            if ($order) {
                return failureMessage('该支付方式仅限提交一次！');
            }
        }

        $merge_package_ids = '';

        if ($package->merge_package_type == DEFAULT_TYPE_ONE) {
            $merge_package_ids = $package->merge_package_ids;
        }

        $order_id = CarPackageOrder::create([
            'brand_id' => $package->brand_id,
            'category_id' => $package->category_id,
            'store_id' => $store->id,
            'order_sn' => $order_sn,
            'package_id' => $package->id,
            'package_title' => $package->title,
            'package_pic' => $package->pic,
            'merge_package_ids' => $merge_package_ids,
            'user_id' => $user->id,
            'user_name' => $user->name,
            'user_phone' => $user->phone,
            'price' => $package->price,
            'order_price' => 0,
            'status' => $status,
            'payment_type' => $param['payment_type'],
            'remarks_pics' => $param['remarks_pics'],
        ])->id;

        if ($param['payment_type'] == ORDER_PAYMENT_TYPE_WECHAT) {
            if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
                $js_sdk = $app->jssdk;

                return successMessage(['data' => $js_sdk->bridgeConfig($result['prepay_id'], true), 'order_id' => $order_id]);
            } else {
                return failureMessage($result['return_msg']);
            }
        } else {
            return successMessage(['order_id' => $order_id]);
        }
    }

    public static function pay($order_id)
    {
        $user = Auth::user();
        $order = self::detail($order_id);
        $order_sn = self::sn();

        $app = Factory::payment(config('wechat.payment.default'));

        $result = $app->order->unify([
            'body' => '购买'.$order->package_title.'套餐',
            'out_trade_no' => $order_sn,
            'total_fee' => app()->environment(['local','staging']) ? 1 : $order['price'] * 100,
            'trade_type' => "JSAPI",
            'spbill_create_ip' => request()->ip(),
            'openid' => $user->app_open_id
        ]);

        $order->order_sn = $order_sn;
        $order->save();

        if ($result['return_code'] == 'SUCCESS' && $result['result_code'] == 'SUCCESS') {
            $js_sdk = $app->jssdk;

            return ['code' => 'SUCCESS', 'data' => $js_sdk->bridgeConfig($result['prepay_id'], true), 'order_id' => $order_id];
        } else {
            return ['code' => 'FAIL', 'data' => $result['return_msg']];
        }
    }

    public static function refund($order, $refund_desc, $notify_url = '')
    {
        $user = UserService::userInfo($order->model()->user_id);

        if (!$user->app_open_id && !$user->union_id) {
            return failureMessage('该用户未绑定小程序信息！');
        }

        if ($order->model()->order_sn == $order->model()->payment_sn) {
            return failureMessage('旧系统用户无法线上退款，请选择线下退款！');
        }

        $refund_sn = self::refundSn();

        $app = Factory::payment(config('wechat.payment.default'));

        // 参数分别为：微信订单号、商户退款单号、订单金额、退款金额、其他参数
        $result = $app->refund->byTransactionId(
            $order->model()->payment_sn,
            $refund_sn,
            $order->model()->price * 100,
            $order->refund_price * 100,
            [
                'refund_desc' => $refund_desc,
                'notify_url' => $notify_url // 回调路径
            ]
        );

        if ($result['return_code'] != 'SUCCESS') {
            return failureMessage($result['return_msg']);
        }

        if ($result['result_code'] != 'SUCCESS') {
            return failureMessage($result['err_code_des']);
        }

        return successMessage(['refund_sn' => $refund_sn, 'refund_payment_sn' => $result['refund_id']]);
    }

    public static function detail($order_id = 0)
    {
        $user = Auth::user();

        if ($order_id) {
            $order = CarPackageOrder::find($order_id);
        } else {
            $order = CarPackageOrder::where([
                'user_id' => $user->id,
            ])->orderBy('id', 'desc')->first();
        }

        return $order;
    }

    public static function attr($order_id, $user_id)
    {
        $order = self::detail($order_id);

        if ($order->merge_package_ids) {
            $merge_package_ids = json_decode($order->merge_package_ids);

            foreach ($merge_package_ids as $key => $value) {
                $merge_order_attr = CarPackageOrderAttr::where([
                    'user_id' => $user_id,
                    'order_id' => $order_id,
                    'merge_package_id' => $value,
                ])->where('type_id', '!=', 4)->get()->toArray();

                $attr[$value] = self::packageAttr($merge_order_attr, $merge_order_attr[0]['merge_package_title']);
            }

            $give_order_attr = CarPackageOrderAttr::where([
                'user_id' => $user_id,
                'order_id' => $order_id,
            ])->where('type_id', 4)->get()->toArray();

            $give_attr = self::giveAttr($give_order_attr);

            if ($give_attr) {
                $package_attr = array_merge($attr, [$give_attr]);
            } else {
                $package_attr = $attr;
            }
        } else {
            $order_attr = CarPackageOrderAttr::where([
                'user_id' => $user_id,
                'order_id' => $order_id,
            ])->get()->toArray();

            $package_attr = [self::packageAttr($order_attr, $order['package_title'])];
        }

        return $package_attr;
    }

    public static function packageAttr($attrs, $package_title)
    {
        $attr = [
            [
                'id' => 0,
                'type_title' => '套餐类别',
                'children' => [
                    [
                        'content' => $package_title,
                        'checked' => true,
                        'price' => ''
                    ]
                ]
            ]
        ];

        $type = CarPackageType::where('status', DEFAULT_STATUS_SUCCESS)->get()->toArray();

        foreach ($attrs as $key => $value) {
            foreach ($type as $k => &$val) {
                $val['type_title'] = $val['title'];
                if ($value['type_id'] == $val['id']) {
                    $value['content'] = $value['attr_title'];
                    $val['children'][] = $value;
                }
            }
        }

        foreach ($type as $key => $value) {
            if (!isset($value['children'])) {
                unset($type[$key]);
            }
        }

        $attr = array_merge($attr, $type);

        return $attr;
    }

    public static function giveAttr($attrs)
    {
        if (empty($attrs)) {
            return '';
        }

        $give = [];
        $attr = [
            [
                'id' => 0,
                'type_title' => '套餐类别',
                'children' => [
                    [
                        'content' => '增值服务（购买任意套餐赠送）',
                        'checked' => true,
                        'price' => ''
                    ]
                ]
            ]
        ];

        foreach ($attrs as $key => $value) {
            $give['type_title'] = '赠送服务';
            $value['content'] = $value['attr_title'];
            $give['children'][] = $value;
        }

        $give_attr = array_merge($attr, [$give]);

        return $give_attr;
    }

    public static function orderCodeCreate($order_id)
    {
        return WechatService::appQrCode("order_id={$order_id}");
    }

    public static function orderCodeNumber($order_id)
    {
        $random_number = random_int(10000000, 99999999);

        $order = CarPackageOrder::where('code_number', $random_number)->first();

        if ($order) {
            return self::orderCodeNumber($order_id);
        } else {
            return $random_number;
        }
    }

    public static function orderAttrCreate($order)
    {
        $package = CarPackage::find($order->package_id);

        if ($package->merge_package_type == DEFAULT_TYPE_ONE) {
            $merge_ids = json_decode($package->merge_package_ids, true);

            $merge_package = CarPackage::whereIn('id', $merge_ids)->get();

            if ($merge_package) {
                foreach ($merge_package as $key => $value) {
                    $package_attr = json_decode($value->attrs, true);

                    if ($package_attr) {
                        foreach ($package_attr as $k => $val) {
                            $create_data = [
                                'user_id' => $order->user_id,
                                'package_id' => $package->id,
                                'order_id' => $order->id,
                                'package_title' => $package->title,
                                'package_pic' => $package->pic,
                                'type_id' => $val['type_id'],
                                'merge_package_id' => $value['id'],
                                'merge_package_title' => $value['title'],
                                'attr_title' => $val['content'],
                                'usable_number' => $val['count'],
                                'total_number' => $val['count'],
                                'used_number' => 0
                            ];

                            if ($val['type_id'] == 4) {
                                $attr = CarPackageOrderAttr::where([
                                    'user_id' => $order->user_id,
                                    'order_id' => $order->id,
                                    'package_id' => $package->id,
                                    'attr_title' => $val['content'],
                                    'type_id' => $val['type_id']
                                ])->first();

                                if (!$attr) {
                                    CarPackageOrderAttr::create($create_data);
                                } else {
                                    $attr->delete();
                                    CarPackageOrderAttr::create($create_data);
                                }
                            } else {
                                CarPackageOrderAttr::create($create_data);
                            }
                        }
                    }
                }
            }
        } else {
            $package_attr = json_decode($package->attrs, true);

            if ($package_attr) {
                foreach ($package_attr as $key => $value) {
                    CarPackageOrderAttr::create([
                        'user_id' => $order->user_id,
                        'package_id' => $package->id,
                        'order_id' => $order->id,
                        'package_title' => $package->title,
                        'package_pic' => $package->pic,
                        'type_id' => $value['type_id'],
                        'attr_title' => $value['content'],
                        'usable_number' => $value['count'],
                        'total_number' => $value['count'],
                        'used_number' => 0
                    ]);
                }
            }
        }
    }

    /**
     * 计算项目已使用的费用
     * @param $order
     * @return array
     */
    public static function attrUsedPrice($order)
    {
        $package = CarPackage::find($order->package_id);
        $used_prices = [];
        $sum_price = 0;

        if ($package->merge_package_type == DEFAULT_TYPE_ONE) {
            $merge_ids = json_decode($package->merge_package_ids, true);

            $merge_package = CarPackage::whereIn('id', $merge_ids)->get();

            if ($merge_package) {
                foreach ($merge_package as $key => $value) {
                    $package_attr = json_decode($value->attrs, true);

                    if ($package_attr) {
                        foreach ($package_attr as $k => $val) {
                            $package_used = CarPackageOrderAttr::where('order_id', $order->id)
                                ->where('used_number', '!=', 0)
                                ->where('attr_title', $val['content'])
                                ->first();

                            if ($package_used) {
                                if ($val['type_id'] == 4) {
                                    $search_arr = array_search($val['content'], array_column($used_prices, 'content'));

                                    if (!$search_arr) {
                                        $used_prices[$k]['content'] = $val['content'];
                                        $used_prices[$k]['price'] = $val['price'];
                                        $used_prices[$k]['used_number'] = $package_used['used_number'];
                                        $sum_price += $val['price'];
                                    }
                                } else {
                                    $used_prices[$k]['content'] = $val['content'];
                                    $used_prices[$k]['price'] = $val['price'];
                                    $used_prices[$k]['used_number'] = $package_used['used_number'];
                                    $sum_price += $val['price'];
                                }
                            }
                        }
                    }
                }
            }
        } else {
            $package_attr = json_decode($package->attrs, true);

            if ($package_attr) {
                foreach ($package_attr as $k => $val) {
                    $package_used = CarPackageOrderAttr::where('order_id', $order->id)
                        ->where('used_number', '!=', 0)
                        ->where('attr_title', $val['content'])
                        ->first();

                    if ($package_used) {
                        $used_prices[$k]['content'] = $val['content'];
                        $used_prices[$k]['price'] = $val['price'];
                        $used_prices[$k]['used_number'] = $package_used['used_number'];
                        $sum_price += $val['price'];
                    }
                }
            }

        }

        return ['sum_price' => $sum_price, 'used_prices' => $used_prices];
    }

    public static function orderStatusSwitch($status = 0)
    {
        switch ($status) {
            case 1:
                $status = ORDER_STATUS_UNPAID;
                break;
            case 2:
                $status = ORDER_STATUS_PAID;
                break;
        }

        return $status;
    }

    public static function orderStatusTitle($status = 0)
    {
        switch ($status) {
            case 1:
                $status = '已付款';
                break;
            case 2:
                $status = '待付款';
                break;
            case 0:
                $status = '已取消';
                break;
            case 3:
                $status = '已完成';
                break;
            case 4:
                $status = '已退款';
                break;
            case 5:
                $status = '待审核';
                break;
        }

        return $status;
    }

    /**
     * 订单号生成
     * @return string
     */
    public static function sn()
    {
        return date('Ymd') . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
    }

    /**
     * 退款订单号生成
     * @return string
     */
    public static function refundSn()
    {
        return 'r' . date('Ymd') . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99));
    }
}